<?php

namespace core;

class App
{
    public static $debug = true;
    private static $config = [];
    private static $route = [];

    //执行应用程序
    public static function run(Request $request = null)
    {
        $request = is_null($request) ? Request::instance() : $request;

        //初始化配置信息
        self::init();

        //初始化助手函数
        include(CORE_PATH . "helper.php");

        //初始化请求
        $route = self::route($request);

        //路由分发 执行
        self::implement($request, $route);
    }

    public static function implement($request, $moduleAry)
    {
        $module = strip_tags(strtolower($moduleAry[0] ?: self::$config['default_module']));
        $controller = strip_tags(strtolower($moduleAry[1] ?: self::$config['default_controller']));
        $action = strip_tags(strtolower($moduleAry[2] ?: self::$config['default_action']));

        //设置当前的模块名
        $request->module($module);
        //设置当前的模块名
        $request->controller($controller);
        //设置当前的模块名
        $request->action($action);

        //当前应用控制器文件路径
        $mvcControllerFile = sprintf("%s" . $module . "/controller" . "/%s" . '.php', APP_PATH, $controller);
        $mvcControllerClass = "\\app\\" . $module . "\\controller\\" . $controller;
        //检测控制器文件是否存在
        if (file_exists($mvcControllerFile)) {
            //检查类是否已定义
            if (class_exists($mvcControllerClass)) {
                //实例化数据库操作类
                new Db();

                //实例化当前应用控制器
                $myfC = new $mvcControllerClass();

                //检查类方法是否存在
                if (is_object($myfC) && method_exists($myfC, $action)) {
                    //初始化系统方法 模板引擎
                    $myfC->_sys_init_action($module, $controller);
                    //执行前置方法
                    $myfC->_before_action();
                    //执行用户方法
                    $myfC->{$action}();
                    //执行后置方法
                    $myfC->_after_action();
                } else {
                    header('Content-Type:application/json; charset=utf-8');
                    echo "The method " . $action . " () not found in class " . ucfirst($controller);
                }
            } else {
                header('Content-Type:application/json; charset=utf-8');
                echo "Unable to load class：" . $controller;
            }
        } else {
            header('Content-Type:application/json; charset=utf-8');
            echo "404 The page not found：" . $mvcControllerFile;
        }
    }

    public static function init()
    {
        //载入应用基础配置
        Config::load(CONFIG_PATH . 'config.php');

        //载入应用cookie配置
        Config::load(CONFIG_PATH . 'cookie.php', 'cookie');

        //载入应用log配置
        Config::load(CONFIG_PATH . 'log.php', 'log');

        //载入应用数据库配置
        Config::load(CONFIG_PATH . 'mysql.php', 'mysql');

        //载入应用数据库配置
        Config::load(CONFIG_PATH . 'redis.php', 'redis');

        //载入应用session配置
        Config::load(CONFIG_PATH . 'session.php', 'session');

        //载入应用视图配置
        Config::load(CONFIG_PATH . 'view.php', 'view');

        //载入公共函数文件
        $functionFile = CONFIG_PATH . "function.php";
        if (is_file($functionFile)) {
            include($functionFile);
        }

        // 应用debug模式:true/false
        self::$debug = Config::get('debug');
        if (!self::$debug) {
            ini_set('display_errors', 'Off');
        } elseif (!IS_CLI) {
            // 重新申请一块比较大的 buffer
            if (ob_get_level() > 0) {
                $output = ob_get_clean();
            }
            ob_start();
            if (!empty($output)) {
                echo $output;
            }
        }

        return self::$config = Config::get();
    }

    public static function route($request)
    {
        $routeAry = [];
        $mvc = $request->path();
        if (is_string($mvc)) {
            $routeAry = explode('/', $mvc);
        }

        //记录路由和请求信息
        if (self::$debug) {
            Log::record('[ ROUTE ] ' . var_export($request->url(true), true), 'info');
            Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
            Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
        }

        return $routeAry;
    }

}